﻿using LitJson;
using LNet;
using OestsCommon.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Timers;
using Utils;

namespace OestsServer.Net
{
    //public interface IClientMnager2
    //{
    //    /// <summary>
    //    /// 连接数量
    //    /// </summary>
    //    int ConnectCount { get; }
    //    void AddClient(ClientChannel client);
    //    void DeleteClient(ClientChannel client);
    //    ClientChannel GetClient(UserType userType, int userId);
    //    bool CheckUserIsExist(ProjectType cType, int userDbId);
    //    bool CheckUserIsExist(int userDbId);

    //    /// <summary>
    //    /// 下线某个账号
    //    /// </summary>
    //    /// <param name="userId"></param>
    //    void LogoffAccount(int userId);

    //    /// <summary>
    //    /// 获取在线用户
    //    /// </summary>
    //    /// <returns></returns>
    //    List<User> GetOnlineUsers();

    //    /// <summary>
    //    /// 获取某个学生
    //    /// </summary>
    //    /// <param name="stuId"></param>
    //    /// <returns></returns>
    //    Student GetStudentById(int stuId);
    //}


    public class ClientManager //: IClientMnager 
    {
        /// <summary>
        /// 心跳频率 10秒
        /// </summary>
        const int HEART_RATE = 10000;
        /// <summary>
        /// 连接保持时常（10000000 = 1秒）,超过20秒就断开连接
        /// </summary>
        const int KEEP_TIME = 200000000;

        protected List<ClientChannel> clientList = new List<ClientChannel>();

        /// <summary>
        /// 连接数量
        /// </summary>
        public int ConnectCount { get { return clientList.Count; } }

        public ClientManager()
        {
            Thread thread = new Thread(ConnectState)
            {
                IsBackground = true
            };
            thread.Start();
        }
        private System.Timers.Timer timer;

        private void ConnectState()
        {
            //10秒检测一次客户端是否连接
            timer = new System.Timers.Timer(HEART_RATE);
            timer.Elapsed += new System.Timers.ElapsedEventHandler(HeartBeatHandler);//到达时间执行事件
            timer.AutoReset = true;//设置是执行一次（false）还是一直执行(true)；
            timer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件；
            timer.Start();
        }

        private void HeartBeatHandler(object sender, ElapsedEventArgs e)
        {
            long nowTime = DateTime.Now.Ticks;
            lock (clientList)
            {
                for (int i = clientList.Count - 1; i >= 0; i--)
                {
                    var client = clientList[i];
                    if (nowTime - client.lastPing > KEEP_TIME)
                    {
                        string info = string.Format("{0}[{1}][{2}]is disconnected !", client.listenerName, client.IPDes, client.UserDes);
                        LogNetDebug.Log(info);
                        client.UpdateLogoutTime();
                        client.Close();
                        clientList.RemoveAt(i);
                    }
                }
            }
        }

        //添加一个客户端
        public void AddClient(ClientChannel client)
        {
            lock (clientList)
            {
                clientList.Add(client);
            }
        }
        public void DeleteClient(ClientChannel client)
        {
            lock (clientList)
            {
                for (int i = 0; i < clientList.Count; i++)
                {
                    if (clientList[i] == client)
                    {
                        // clientList[i].Close();
                        clientList[i] = null;
                        clientList.RemoveAt(i);
                        break;
                    }
                }
            }
        }


        public Student GetStudentById(int stuId)
        {
            lock (clientList)
            {
                foreach (var clientChannel in clientList)
                {
                    if (clientChannel.Student == null) continue;

                    if (clientChannel.Student.DBid == stuId)
                    {
                        return clientChannel.Student;
                    }

                }
                return null;
            }

        }

        /// <summary>
        /// 检查一个用户是否在线
        /// </summary>
        /// <param name="cType"></param>
        /// <param name="uType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool CheckUserIsExist(int userDbId)
        {
            lock (clientList)
            {
                foreach (var client in clientList)
                {
                    if (client == null) continue;
                    if (client.User == null) continue;
                    if (client.User.DBid == userDbId)
                        return true;

                }
            }
            return false;
        }

        /// <summary>
        /// 检查一个用户是否在线
        /// </summary>
        /// <param name="cType"></param>
        /// <param name="userDbId"></param>
        /// <returns></returns>
        public bool CheckUserIsExist(ProjectType cType, int userDbId)
        {
            lock (clientList)
            {
                foreach (var client in clientList)
                {
                    if (client != null)
                    {
                        UnityClientChannel unityClient = client as UnityClientChannel;
                        if (unityClient.ProjectType == cType)
                        {
                            if (client.User == null)
                            {
                                continue;
                            }
                            if (client.User.DBid == userDbId)
                                return true;
                        }
                    }

                }
            }
            return false;
        }

        public ClientChannel GetClient(UserType userType, int userId)
        {
            lock (clientList)
            {
                for (int i = clientList.Count - 1; i > -1; i--)
                {
                    if (clientList[i].User != null)
                    {
                        if (clientList[i].User.Type == userType && clientList[i].User.DBid == userId)
                        {
                            return clientList[i];
                        }
                    }
                }
            }
            return null;
        }

        public void LogoffAccount(int userId)
        {

            void offline(ClientChannel client, User user)
            {
                Response response = new Response(PacketKey.ForceAccountOffline);
                response.ReturnCode = ReturnCode.Success;
                response.DataObject = user;
                client.Send(response);
            }
            lock (clientList)
            {
                for (int i = clientList.Count - 1; i >= 0; i--)
                {
                    var item = clientList[i];
                    if (item == null) continue;
                    if (item.User == null) continue;
                    if (item.User.DBid == userId)
                    {
                        offline(item, item.User);
                        //if (item.IsConnected)
                        //    item.Close();//使用这个会导致客户端崩溃
                        item.UpdateLogoutTime();
                        clientList.Remove(item);
                    }
                }
            }
        }

        public List<IpUser> GetOnlineUsers()
        {
            lock (clientList)
            {
                var clientUsers = clientList.Where(x => x.User != null && x.User.DBid > 0 && x.User.Type != UserType.Admin);
                if (clientUsers != null)
                    //return clientUsers.Select(x =>  x.User).ToList();
                    return clientUsers.Select(x => new IpUser() {User = x.User,IP = x.IPDes }).ToList();
                return null;
            }
        }
    }
}
